package com.run_java_test.t.test_run;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.tools.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/dynamic")
public class UploadController {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Autowired
    private DynamicControllerRegistry dynamicControllerRegistry;

    @Autowired
    private DynamicControllerRemover dynamicControllerRemover;
    private static final String CLASS_DIR = "D:\\a2software_cache\\IDEAProject\\self\\java_study_springboot_run_java_source_code\\sp33_run_java_code\\target\\classes\\com\\run_java_test\\test_code\\"; // 替换为你的包路径

    @PostMapping("/upload")
    public String uploadAndLoadJavaFile(@RequestParam("file") MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();

        if (fileName == null || !fileName.endsWith(".java")) {
            return "Invalid file type. Please upload a .java file.";
        }

        // 自定义的目录路径
        Path customDir = Paths.get(CLASS_DIR);
        // 确保目录存在，如果不存在则创建
        if (!Files.exists(customDir)) {
            Files.createDirectories(customDir);
        }

        // 保存文件
        File javaFile = new File(CLASS_DIR + fileName);
        try (FileOutputStream fos = new FileOutputStream(javaFile)) {
            fos.write(file.getBytes());
        }

        // 编译 Java 文件
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(javaFile);
        boolean success = compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
        fileManager.close();

        if (!success) {
            return "Compilation failed.";
        }

        // 加载类
        try {
            URL[] urls = {new File(CLASS_DIR).toURI().toURL()};
            URLClassLoader classLoader = new URLClassLoader(urls, this.getClass().getClassLoader());

            String className = fileName.substring(0, fileName.lastIndexOf('.'));
            Class<?> loadedClass = Class.forName("com.run_java_test.test_code." + className, true, classLoader);
            Object instance = loadedClass.getDeclaredConstructor().newInstance();
            System.out.println("className: " + className);
            System.out.println(instance);
            System.out.println(instance.getClass().getCanonicalName());

            // registerControllerBean(className, instance);
            dynamicControllerRemover.removeController(instance.getClass().getCanonicalName());
            dynamicControllerRegistry.registerController(instance.getClass().getCanonicalName(), instance.getClass());

            System.out.println("applicationContext: " + applicationContext.getBean(instance.getClass().getCanonicalName()));

            // 注册 Bean
            // applicationContext.getAutowireCapableBeanFactory().initializeBean(instance, className);
            // applicationContext.getAutowireCapableBeanFactory().autowireBean(instance);

            return "File uploaded, compiled, and class " + className + " loaded successfully.";
        } catch (Exception e) {
            e.printStackTrace();
            return "Failed to load class: " + e.getMessage();
        }
    }

    private void registerControllerBean(String beanName, Object controllerInstance) {
        if (applicationContext instanceof ConfigurableApplicationContext configurableContext) {
            ConfigurableListableBeanFactory beanFactory = configurableContext.getBeanFactory();

            // 移除旧的映射（如果有）
            removeHandlerMappings(beanName);

            // 注册新 Bean
            beanFactory.registerSingleton(beanName, controllerInstance);

            // 更新 RequestMapping
            handlerMapping.afterPropertiesSet();
        } else {
            throw new IllegalStateException("ApplicationContext is not ConfigurableApplicationContext");
        }
    }

    private void removeHandlerMappings(String beanName) {
        // 获取所有的映射
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();

        List<RequestMappingInfo> mappingsToRemove = new ArrayList<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            if (entry.getValue().getBean().equals(beanName)) {
                mappingsToRemove.add(entry.getKey());
            }
        }

        // 移除对应的映射
        for (RequestMappingInfo mappingInfo : mappingsToRemove) {
            handlerMapping.unregisterMapping(mappingInfo);
        }
    }
}
